package com.xframe.xdal.core.domain;

import com.xframe.xdal.core.DataBaseAccess;
import com.xframe.xdal.core.constant.ErrorCode;
import com.xframe.xdal.core.exception.DalFrameException;
import com.xframe.xdal.core.model.*;
import com.xframe.xdal.core.model.mapping.ITableInfo;
import com.xframe.xdal.core.model.mapping.TableInfoBuilder;
import com.xframe.xdal.core.model.page.IPagerModel;
import com.xframe.xdal.core.tran.IDbTransaction;
import com.xframe.xdal.core.tran.XTransaction;
import java.util.Collection;


/**
 * 领域模型的基础Repository接口基础实现
 *
 * @author xufeng
 * @version 1.0
 * @date 2023-03-10
 */
public class BaseRepository implements IRepository {


    protected String dsCode = "main";

    public void setDsCode(String dsCode){
        this.dsCode = dsCode;
    }

    protected DataBaseAccess defDataBaseAccess = DataBaseAccess.getInstanceByName(dsCode);
    @Override
    public void init(){
        defDataBaseAccess = DataBaseAccess.getInstanceByName(dsCode);
    }
    @Override
    public DataBaseAccess getDataBaseAccess(){
        return defDataBaseAccess;
    }
    @Override
    public IDbTransaction beginTransaction(){
        return defDataBaseAccess.beginTransaction();
    }
    @Override
    public IDbTransaction beginTransaction(int level){
        return defDataBaseAccess.beginTransaction();
    }
    /**
     * 提交一个事务
     */
    @Override
    public void commitTran(){
        defDataBaseAccess.commitTran();
    }
    /**
     * 回滚事务
     */
    @Override
    public void rollBackTran(){
        defDataBaseAccess.rollBackTran();
    }

    /**
     * 默认构造函数
     */
    public BaseRepository(){

    }
    /**
     * 根据类型查找对象
     * @param dataType 数据类型
     * @param findOptions 查询条件
     *
     * @return 查询结果集
     */
    @Override
    public <T> T queryModle(Class<?> dataType,FindOptions findOptions){
        try {
            T collection = defDataBaseAccess.findAll(dataType, TableInfoBuilder.BuildTableInfoByAnnotation(dataType),findOptions);
            return collection;
        } catch (DalFrameException e) {
            e.printStackTrace();
            throw e;
        }
    }
    /**
     * 根据类型查找对象
     * @param dataType 数据类型
     * @param tableInfo 表结构
     * @param findOptions 查询条件
     *
     * @return
     */
    @Override
    public <T> T queryModle(Class<?> dataType, ITableInfo tableInfo,FindOptions findOptions){
        try {
            T collection = defDataBaseAccess.findAll(dataType,tableInfo,findOptions);
            return collection;
        } catch (DalFrameException e) {
            e.printStackTrace();
            throw e;
        }
    }


    /**
     * 分页查询
     * @param dataType 被查询的数据类型
     * @param tableInfo 数据表结构
     * @param findOptions 查询设置对象
     *
     * @return IPagerModel分页数据
     */
    @Override
    public <T> IPagerModel<T> queryModleByPage(Class<?> dataType, ITableInfo tableInfo,FindOptions findOptions){
        try {
            IPagerModel<T> baseModelIPagerModel = defDataBaseAccess.findAllByPage(dataType,tableInfo,findOptions);
            return baseModelIPagerModel;
        } catch (DalFrameException e) {
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * 判断一个对象是否存在（AK）
     * @param model 被保存的对象
     *
     * @return true 存在 false 不存在
     */
    @Override
    public boolean exists(IModel model) throws DalFrameException{
        return exists(model,TableInfoBuilder.BuildTableInfoByAnnotation(model.getClass()));
    }

    /**
     * 判断一个对象是否存在（AK）
     * @param model 被保存的对象
     * @param tableInfo 数据表结构
     *
     * @return true 存在 false 不存在
     */
    @Override
    public boolean exists(IModel model, ITableInfo tableInfo) throws DalFrameException{
        try {
            return defDataBaseAccess.isExists(model,tableInfo);
        } catch (DalFrameException e) {
            e.printStackTrace();
            throw e;
        }
    }
    /**
     * 创建一个新的对象到数据库
     * @param model 被保存的对象
     *
     * @return 受影响的行数
     */
    @Override
    public Integer createNew(IModel model) throws DalFrameException {
        return createNew(model,TableInfoBuilder.BuildTableInfoByAnnotation(model.getClass()));
    }
    /**
     * 创建一个新的对象到数据库
     * @param model 被保存的对象
     * @param tableInfo 数据表结构
     *
     * @return 受影响的行数
     */
    @Override
    public Integer createNew(IModel model, ITableInfo tableInfo) throws DalFrameException{
        try {
            if(defDataBaseAccess.isExists(model,tableInfo)){
                throw new DalFrameException(ErrorCode.INSERT_CONFLICT,"DataExist By Ak");
            }
            DataAccessResult<Integer> result = defDataBaseAccess.createNewOperate(model,tableInfo);
            if(!result.getSuccessFlag()){
                throw new DalFrameException(result.getCode(),result.getException().getMessage());
            }
            return result.getResult();
        } catch (DalFrameException e) {
            e.printStackTrace();
            throw e;
        }
    }


    /**
     * 创建一个新的对象到数据库，存在修改，不存在新增
     * @param model 被保存的对象
     * @param tableInfo 数据表结构
     *
     * @return 受影响的行数
     */
    @Override
    public Integer save(IModel model,ITableInfo tableInfo) throws DalFrameException {
        try {
            if(defDataBaseAccess.isExists(model,tableInfo)){
                return update(model,tableInfo,new UpdateAttr(UpdateWhereMode.AK,false));
            }else {
                return createNew(model,tableInfo);
            }
        } catch (DalFrameException e) {
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * 创建一个新的对象到数据库，存在修改，不存在新增
     * @param model 被保存的对象
     * @param tableInfo 数据表结构
     *
     * @return 受影响的行数
     */
    @Override
    public Integer createOrUpdate(IModel model,ITableInfo tableInfo) throws DalFrameException{
        try {
            return defDataBaseAccess.createOrUpdate(model,tableInfo);
        } catch (DalFrameException e) {
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * 修改一个对象到数据库
     * @param model 被保存的对象
     * @param tableInfo 数据表结构
     *
     * @return
     */
    @Override
    public Integer update(IModel model, ITableInfo tableInfo) throws DalFrameException {
        DataAccessResult<Integer> result = defDataBaseAccess.updateOperate(model,tableInfo,true);
        if(!result.getSuccessFlag()){
            throw new DalFrameException(result.getCode(),result.getException().getMessage());
        }
        return result.getResult();
    }

    /**
     * 修改一个对象到数据库
     * @param model 被保存的对象
     * @param tableInfo 数据表结构
     *
     * @return
     */
    @Override
    public Integer update(IModel model, ITableInfo tableInfo,UpdateAttr updateAttr) throws DalFrameException {
        DataAccessResult<Integer> result = defDataBaseAccess.updateOperate(model,tableInfo,updateAttr,true);
        if(!result.getSuccessFlag()){
            throw new DalFrameException(result.getCode(),result.getException().getMessage());
        }
        return result.getResult();
    }


    /**
     * 根据ID删除一个对象
     * @param id 对象ID
     * @param tableInfo 数据表结构
     *
     * @return
     */
    @Override
    public Integer deleteById(Object id, ITableInfo tableInfo) throws DalFrameException {
        DataAccessResult<Integer> result = defDataBaseAccess.deleteOperate(id,tableInfo);
        if(!result.getSuccessFlag()){
            throw new DalFrameException(result.getCode(),result.getException().getMessage());
        }
        return result.getResult();
    }

    /**
     * 删除一个对象
     * @param model 被保存的对象
     * @param tableInfo 数据表结构
     *
     * @return
     */
    @Override
    public Integer delete(IModel model, ITableInfo tableInfo) throws DalFrameException {
        DataAccessResult<Integer> result = defDataBaseAccess.deleteOperate(model,tableInfo);
        if(!result.getSuccessFlag()){
            throw new DalFrameException(result.getCode(),result.getException().getMessage());
        }
        return result.getResult();
    }

    /**
     * 获得一个指定的对象
     * @param dataType 返回的数据类型
     * @param tableInfo 数据表结构
     * @param id id
     * @param refNames 关系名称列表
     *
     * @return T的实例对象
     */
    @Override
    public <T> T findByPK(Class<?> dataType,Object id,ITableInfo tableInfo,String... refNames){
        return defDataBaseAccess.findByPk(dataType,tableInfo,id,refNames);
    }
    /**
     * 获得一个完整的对象
     * @param dataType 返回的数据类型
     * @param tableInfo 数据表结构
     * @param id id
     *
     * @return T的实例对象
     */
    @Override
    public <T> T findByPK(Class<?> dataType,Object id,ITableInfo tableInfo){
        return defDataBaseAccess.findByPk(dataType,tableInfo,id, SysBaseEntity.FULL_DATA);
    }

    /**
     * 根据多个关键字来获得一个实体对象
     * @param dataType 返回的数据类型
     * @param codes 关键字列表
     * @param tableInfo 表结构
     * @param refNames 引用关系列表
     * @return T的实例对象
     */
    public <T> T findbyAk(Class<?> dataType,Collection<Object> codes,ITableInfo tableInfo,String... refNames){
        return defDataBaseAccess.findByAk(AKQueryModel.valueOf(dataType,tableInfo,codes,refNames));
    }
    /**
     * 根据关键字来获得一个实体对象
     * @param dataType 返回的数据类型
     * @param code 关键字
     * @param tableInfo 表结构
     * @param refNames 引用关系列表
     * @return T的实例对象
     */
    @Override
    public <T> T findbyAk(Class<?> dataType,Object code,ITableInfo tableInfo,String... refNames){
        return defDataBaseAccess.findByAk(AKQueryModel.valueOf(dataType,tableInfo,code,refNames));
    }

    /**
     * 根据类型来获关键字来获得一个完整对象
     * @param dataType 返回的数据类型
     * @param code 关键字
     *
     * @return T的实例对象
     */
    @Override
    public <T> T findbyAk(Class<?> dataType,Object code){
        return defDataBaseAccess.findByAk(AKQueryModel.valueOf(dataType,code,SysBaseEntity.FULL_DATA));
    }


    /**
     * 根据条件来删除数据
     * @param tableInfo 表结构
     * @param whereCollection 条件
     *
     * @return 受影响的行数
     */
    @Override
    public Integer deleteMany(ITableInfo tableInfo, ConditionValueCollection whereCollection){
        DataAccessResult<Integer> result = defDataBaseAccess.deleteManyOperate(tableInfo,whereCollection);
        if(!result.getSuccessFlag()){
            throw new DalFrameException(result.getCode(),result.getException().getMessage());
        }
        return result.getResult();
    }
    /**
     * 批量添加数据
     * @param dataType 数据类型
     * @param collection 数据列表
     * @param maxDataLength 单次提交的数据量
     *
     * @return 受影响的行数
     */
    @Override
    public <E> Integer batchCreate(Class<?> dataType, Collection<E> collection, Integer maxDataLength){
        return defDataBaseAccess.batchCreate(dataType,collection,maxDataLength);
    }

    /**
     * 批量保存 不存在insert 存在oracle 走update mySql 走的删除在insert
     * @param dataType 数据类型
     * @param collection 数据列表
     * @param maxDataLength 单次提交的数据量
     *
     * @return 受影响的行数
     */
    @Override
    public <E> Integer batchSave(Class<?> dataType, Collection<E> collection, Integer maxDataLength){
        return defDataBaseAccess.batchSave(dataType,collection,maxDataLength);
    }
    /**
     * 批量保存(存在则修改)
     *
     * @param dataType 数据类型
     * @param collection 被操作的结果
     *
     * @param <E>
     * @return 操作结果
     * @throws DalFrameException 异常
     */
    @Override
    public <E> Integer batchSave(Class<?> dataType, Collection<E> collection){
        return defDataBaseAccess.batchSave(dataType,collection);
    }

    /**
     * 删除后创建数据（适用于多对对关系变）
     * @param tableInfo 表结构
     * @param dataType 数据类型
     * @param keyName 查询的属性名称
     * @param keyValue 查询的属性值
     * @param collection 数据列表
     * @param maxDataLength 单次提交的数据量
     *
     * @return 受影响的行数
     */
    @Override
    @XTransaction
    public <E> DelAndSaveRes deleteAndSave(ITableInfo tableInfo, Class<?> dataType,String keyName,
                                           Object keyValue, Collection<E> collection, Integer maxDataLength) throws DalFrameException {
        DelAndSaveRes res = new DelAndSaveRes();
        IDbTransaction transaction = this.beginTransaction();
        try {
            ConditionValueCollection whereCollection = new ConditionValueCollection();
            whereCollection.add(new ConditionValue(keyName, keyValue));
            Integer delCount = this.deleteMany(tableInfo, whereCollection);
            res.setDelCount(delCount);
            Integer addCount = 0;
            if(collection != null && collection.size() > 0) {
                addCount = this.batchCreate(dataType, collection, maxDataLength);
                res.setSaveCount(addCount);
            }
            transaction.commit();
        } catch (DalFrameException dalFrameException){
            transaction.rollBack();
            throw dalFrameException;
        } catch (Exception ex){
            transaction.rollBack();
            throw new DalFrameException(ErrorCode.SQL_ERROR,ex.getMessage());
        }
        return res;
    }



    /**
     * 批量修改
     * @param tableInfo 表结构
     * @param setWrapCollection set子句
     * @param whereCollection 批量where条件
     *
     * @return 受影响的行数
     */
    @Override
    public Integer updateMany(ITableInfo tableInfo,SetWrapCollection setWrapCollection,
                              ConditionValueCollection whereCollection){
        return getDataBaseAccess().updateMany(tableInfo, setWrapCollection, whereCollection);
    }




}
